using System;
using System.Globalization;
using NUnit.Framework;
using ValidationFramework.Reflection;

namespace ValidationFramework.Tests
{

	[TestFixture]
	public class DateTimeConversionRuleTest
	{
		const string expectedErrorMessage = "expectedErrorMessage";
		const string expectedRuleSet = "EXPECTEDRULESET";
		private const string expectedFormat = "YYYY MM DD";
		const DateTimeStyles expectedDateTimeStyles = DateTimeStyles.AllowInnerWhite;

		[TestFixture]
		public class Contruction
		{
			[Test]
			public void AllParams()
			{
				var rule = new DateTimeConversionRule(expectedFormat, DateTimeFormatInfo.InvariantInfo, expectedDateTimeStyles);
				Assert.AreEqual(expectedFormat, rule.Format);
				Assert.AreEqual(expectedDateTimeStyles, rule.DateTimeStyles);
			}
			[Test]
			public void NoParams()
			{
				var rule = new DateTimeConversionRule();
				Assert.AreEqual(null, rule.Format);
				Assert.AreEqual(DateTimeStyles.None, rule.DateTimeStyles);
			}
			[Test]
			public void ErrorMessageParams()
			{
			    const string expectedErrorMessage = "ExpectedErrorMessage";
                var rule = new DateTimeConversionRule();
				Assert.AreEqual(null, rule.Format);
				Assert.AreEqual(DateTimeStyles.None, rule.DateTimeStyles);
			}

		}

		[TestFixture]
		public class IsEquivalent
		{

			[Test]
			public void FormatCompare()
			{
				var rule1 = new DateTimeConversionRule("format1", null, DateTimeStyles.None);
				var rule2 = new DateTimeConversionRule("format1", null, DateTimeStyles.None);
				Assert.IsTrue(rule1.IsEquivalent(rule2));

				rule1 = new DateTimeConversionRule("format1", null, DateTimeStyles.None);
				rule2 = new DateTimeConversionRule("format2", null, DateTimeStyles.None);
				Assert.IsFalse(rule1.IsEquivalent(rule2));
			}

			[Test]
			public void DateTimeFormatInfoCompare()
			{
				var rule1 = new DateTimeConversionRule(null, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);
				var rule2 = new DateTimeConversionRule(null, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);
				Assert.IsTrue(rule1.IsEquivalent(rule2));

				rule1 = new DateTimeConversionRule(null, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);
				rule2 = new DateTimeConversionRule(null, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None);
				Assert.IsFalse(rule1.IsEquivalent(rule2));
			}

			[Test]
			public void DateTimeStylesCompare()
			{
				var rule1 = new DateTimeConversionRule(null, null, DateTimeStyles.NoCurrentDateDefault);
				var rule2 = new DateTimeConversionRule(null, null, DateTimeStyles.NoCurrentDateDefault);
				Assert.IsTrue(rule1.IsEquivalent(rule2));

				rule1 = new DateTimeConversionRule(null, null, DateTimeStyles.NoCurrentDateDefault);
				rule2 = new DateTimeConversionRule(null, null, DateTimeStyles.AllowWhiteSpaces);
				Assert.IsFalse(rule1.IsEquivalent(rule2));
			}
		}



		[TestFixture]
		public class RuleInterpretation
		{
			[Test]
			public void Simple()
			{
				var rule = new DateTimeConversionRule(null, null, DateTimeStyles.None);
				Assert.IsNotNull(rule.RuleInterpretation);

			}
		}

		[TestFixture]
		public class Validate
		{

			[Test]
			public void Simple()
			{
				var rule = new DateTimeConversionRule(null, null, DateTimeStyles.None);

				Assert.IsTrue(rule.Validate(null, null, null, null));
				Assert.IsTrue(rule.Validate(null, string.Empty, null, null));
				Assert.IsFalse(rule.Validate(null, "sdf", null, null));
				Assert.IsTrue(rule.Validate(null, "12 January 2005", null, null));

			}
			[Test]
			public void WithFormat()
			{
				var rule = new DateTimeConversionRule("dd/MM/yyyy", null, DateTimeStyles.None);

				Assert.IsTrue(rule.Validate(null, null, null, null));
				Assert.IsTrue(rule.Validate(null, string.Empty, null, null));
				Assert.IsFalse(rule.Validate(null, "sdf", null, null));
				Assert.IsTrue(rule.Validate(null, "12/01/2001", null, null));

			}

		}

		[TestFixture]
		public class CheckTypes
		{


			[Test]
			public void Simple()
			{
			    var rule = new DateTimeConversionRule(null, null, DateTimeStyles.None);
			    rule.CheckType(new MockInfoDescriptor(TypePointers.StringTypeHandle, "foo"));
			}


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Member 'foo' must be a 'System.String' to be used for the ValidationFramework.DateTimeConversionRule. Actual Type 'System.Int32'.\r\nParameter name: value")]
            public void ExceptionIncorrectType()
            {
                var rule = new DateTimeConversionRule(null, null, DateTimeStyles.None);
                rule.CheckType(new MockInfoDescriptor(TypePointers.IntTypeHandle, "foo"));
            }
		}

	}
}